import React from "react";
import type { FC, ReactNode } from "react";
import { useState, useRef, useEffect } from "react";
import ReactMarkdown from "react-markdown";
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
import {
  coldarkCold,
  vscDarkPlus,
} from "react-syntax-highlighter/dist/esm/styles/prism";
import remarkGfm from "remark-gfm";
import rehypeRaw from "rehype-raw";
import remarkBreaks from "remark-breaks"; // 支持单行换行
import rehypeSlug from "rehype-slug"; // 为标题添加ID
import rehypeSanitize from "rehype-sanitize"; // 内容净化，避免XSS风险
import remarkMath from "remark-math"; // 解析数学公式
import rehypeKatex from "rehype-katex"; // 使用KaTeX渲染数学公式
import "katex/dist/katex.min.css"; // 导入KaTeX样式

// 语言名称映射，支持更多语言显示
const languageMap: Record<string, string> = {
  java: "java",
  js: "javascript",
  ts: "typescript",
  jsx: "jsx",
  tsx: "tsx",
  sh: "bash",
  shell: "bash",
  zsh: "bash",
  py: "python",
  rb: "ruby",
  cs: "csharp",
  yml: "yaml",
  md: "markdown",
  c: "c",
  cpp: "cpp",
  css: "css",
  html: "html",
  json: "json",
  xml: "xml",
  sql: "sql",
  go: "go",
  rust: "rust",
  swift: "swift",
  kotlin: "kotlin",
  php: "php",
};

export interface MarkdownRendererProps {
  /** Markdown格式的内容字符串 */
  content: string;
  /** 是否允许渲染HTML (小心XSS风险) */
  allowHtml?: boolean;
  /** 自定义CSS类名 */
  className?: string;
}

/**
 * 复制内容到剪贴板
 * @param text 要复制的文本内容
 * @returns 返回一个Promise，成功时返回true，失败时返回false
 */
const copyToClipboard = async (text: string): Promise<boolean> => {
  try {
    await navigator.clipboard.writeText(text);
    return true;
  } catch (err) {
    console.error("复制到剪贴板失败:", err);
    return false;
  }
};

/**
 * 代码块组件，带有复制功能
 */
const CodeBlock: FC<{
  language: string;
  children: ReactNode;
  className?: string;
}> = ({ language, children, className, ...props }) => {
  const [copied, setCopied] = useState(false);
  const [folded, setFolded] = useState(false);
  const codeRef = useRef<HTMLDivElement>(null);

  // 映射语言别名到实际支持的语言
  const mappedLanguage = languageMap[language] || language || "text";

  const handleCopy = async () => {
    if (!children) return;

    const text =
      typeof children === "string"
        ? children
        : Array.isArray(children)
        ? children.join("")
        : "";

    const success = await copyToClipboard(text);

    if (success) {
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    }
  };

  // 计算代码行数，用于展示折叠提示
  const linesCount =
    typeof children === "string" ? children.split("\n").length : 0;

  return (
    <div
      className="relative group overflow-hidden rounded-md my-4"
      ref={codeRef}
    >
      {/* 语言标签 - 绝对定位到右上角 */}
      {language && (
        <span className="absolute right-[76px] top-2 z-10 text-xs text-gray-700 dark:text-gray-500 bg-gray-100 dark:bg-gray-700/50 px-2 py-1 rounded-md">
          {mappedLanguage}
        </span>
      )}

      {/* 复制按钮 - 绝对定位到右上角 */}
      <button
        onClick={handleCopy}
        className="absolute right-2 top-2 z-10 bg-gray-700/50 hover:bg-gray-700/80 text-gray-100 rounded px-2 py-1 text-xs transition-all"
        title="复制代码"
      >
        {copied ? "已复制!" : "复制"}
      </button>

      {/* 折叠按钮 - 只有当行数大于10时才显示 */}
      {linesCount > 10 && (
        <button
          onClick={() => setFolded(!folded)}
          className="absolute left-2 top-2 z-10 bg-gray-700/50 hover:bg-gray-700/80 text-gray-100 rounded px-2 py-1 text-xs transition-all flex items-center gap-1"
          title={folded ? "展开代码" : "折叠代码"}
        >
          {folded ? (
            <>
              <svg
                xmlns="http://www.w3.org/2000/svg"
                className="h-3 w-3"
                fill="none"
                viewBox="0 0 24 24"
                stroke="currentColor"
              >
                <path
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  strokeWidth={2}
                  d="M19 9l-7 7-7-7"
                />
              </svg>
              展开
            </>
          ) : (
            <>
              <svg
                xmlns="http://www.w3.org/2000/svg"
                className="h-3 w-3"
                fill="none"
                viewBox="0 0 24 24"
                stroke="currentColor"
              >
                <path
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  strokeWidth={2}
                  d="M5 15l7-7 7 7"
                />
              </svg>
              折叠
            </>
          )}
        </button>
      )}

      {/* 折叠状态提示 - 当代码被折叠时显示 */}
      {folded ? (
        <div
          className="bg-gray-100 dark:bg-gray-800 p-4 text-sm text-gray-700 dark:text-gray-300 cursor-pointer rounded-md"
          onClick={() => setFolded(false)}
        >
          <div className="flex items-center gap-2">
            <svg
              xmlns="http://www.w3.org/2000/svg"
              className="h-5 w-5"
              fill="none"
              viewBox="0 0 24 24"
              stroke="currentColor"
            >
              <path
                strokeLinecap="round"
                strokeLinejoin="round"
                strokeWidth={2}
                d="M19 9l-7 7-7-7"
              />
            </svg>
            <span>
              点击展开 {linesCount} 行代码 ({mappedLanguage})
            </span>
          </div>
          <div className="mt-2 text-xs text-gray-500">
            {typeof children === "string" &&
              children
                .split("\n")
                .slice(0, 2)
                .map((line, i) => (
                  <div key={i} className="truncate">
                    {line}
                  </div>
                ))}
            <div className="truncate">...</div>
          </div>
        </div>
      ) : (
        <SyntaxHighlighter
          style={
            typeof document !== "undefined" &&
            document.documentElement.classList.contains("dark")
              ? vscDarkPlus
              : coldarkCold
          }
          language={mappedLanguage}
          PreTag="div"
          className={`rounded-md ${
            className || ""
          } mt-2 max-w-full overflow-x-auto`}
          wrapLongLines={true}
          showLineNumbers={
            mappedLanguage !== "text" && String(children).split("\n").length > 5
          }
          customStyle={{
            maxWidth: "100%",
            overflowX: "auto",
          }}
          {...props}
        >
          {String(children).replace(/\n$/, "")}
        </SyntaxHighlighter>
      )}
    </div>
  );
};

/**
 * 任务列表项组件
 */
const TaskListItem: FC<{
  checked: boolean;
  children: ReactNode;
}> = ({ checked, children }) => {
  return (
    <li className="flex items-start my-1">
      <div className="flex-shrink-0 mt-1 mr-2">
        <div
          className={`w-4 h-4 border rounded flex items-center justify-center ${
            checked
              ? "bg-blue-500 border-blue-500 dark:bg-blue-600 dark:border-blue-600"
              : "border-gray-300 dark:border-gray-600"
          }`}
        >
          {checked && (
            <svg
              className="w-3 h-3 text-white"
              fill="none"
              viewBox="0 0 24 24"
              stroke="currentColor"
            >
              <path
                strokeLinecap="round"
                strokeLinejoin="round"
                strokeWidth={3}
                d="M5 13l4 4L19 7"
              />
            </svg>
          )}
        </div>
      </div>
      <div className="flex-1">{children}</div>
    </li>
  );
};
const MarkdownRenderer: FC<MarkdownRendererProps> = ({
  content,
  allowHtml = false,
  className = "",
}) => {
  const [processedContent, setProcessedContent] = useState(content);

  // 处理混合格式的Markdown内容，确保代码块和表格正确渲染
  useEffect(() => {
    let processed = content;

    // 在纯HTML标签添加间距，使其不与Markdown语法冲突
    processed = processed
      .replace(/(<\/?h[1-6].*?>)/g, "\n\n$1\n\n")
      .replace(/(<\/?div.*?>)/g, "\n\n$1\n\n")
      .replace(/(<\/?p.*?>)/g, "\n\n$1\n\n");

    // 处理可能的HTML代码块，将```开头结尾的代码块转换为更兼容的格式
    processed = processed.replace(
      /```(\w+)\n([\s\S]*?)```/g,
      (_, lang, code) => {
        return `\n\n\`\`\`${lang}\n${code.trim()}\n\`\`\`\n\n`;
      }
    );

    // 更好地处理数学公式格式
    // 处理行内公式，确保前后有空格以便正确解析
    processed = processed.replace(/\$([^$\n]+?)\$/g, " $$$1$ ");

    // 处理块级公式，确保它们被正确识别
    processed = processed.replace(/\$\$([\s\S]+?)\$\$/g, (_, content) => {
      // 确保块级公式前后有空行以便正确解析
      return `\n\n$$\n${content.trim()}\n$$\n\n`;
    });

    // 确保HTML标签不会干扰Markdown语法
    processed = processed.replace(
      /(\n|^)#{1,6}\s/g,
      (match) => `\n${match.trim()} `
    );

    // 优化内联代码块的格式
    processed = processed.replace(/`([^`]+)`/g, "`$1`");

    // 修复任务列表格式 [x]
    processed = processed.replace(/(\s*)-\s*\[([x ])\]\s+/g, "$1- [$2] ");

    // 表格处理简化
    if (processed.includes("|")) {
      // 确保表格前后有空行，识别为独立块
      processed = processed.replace(/^((?:\|[^\n]*\|\s*\n)+)/gm, "\n\n$1\n\n");

      // 确保表格单元格内容前后有空格
      processed = processed.replace(
        /\|([^|\n]*)\|/g,
        (_, content) => `| ${content.trim()} |`
      );
    }

    // 优化HTML中的列表项，确保能被正确解析
    processed = processed.replace(/<li>(.*?)<\/li>/g, "<li>\n\n$1\n\n</li>");

    setProcessedContent(processed);
  }, [content]);

  // 配置插件数组
  const remarkPlugins = [
    remarkGfm, // GitHub风格Markdown
    remarkBreaks, // 支持单行换行
    remarkMath, // 解析数学公式
  ];

  const rehypePlugins = [
    rehypeSlug, // 为标题添加ID
    rehypeKatex, // 渲染数学公式
    ...(allowHtml ? [rehypeRaw] : [rehypeSanitize]), // 如果允许HTML，使用rehypeRaw，否则使用rehypeSanitize
  ];

  return (
    <div
      className={`markdown-renderer prose dark:prose-invert max-w-none ${className}`}
    >
      <style>{`
        /* 表格样式 */
        .markdown-renderer table {
          border-collapse: separate;
          border-spacing: 0;
          margin: 1.5rem 0;
          width: 100%;
          font-size: 0.9em;
          border: 1px solid #e2e8f0;
          border-radius: 0.5rem;
          overflow: hidden;
          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
          table-layout: auto;
          white-space: nowrap;
        }
        
        /* 确保表格容器可以水平滚动 */
        .markdown-renderer .overflow-x-auto {
          overflow-x: auto;
          -webkit-overflow-scrolling: touch;
          scrollbar-width: thin;
          max-width: 100%;
        }
        
        /* 自定义滚动条 */
        .markdown-renderer .overflow-x-auto::-webkit-scrollbar {
          height: 6px;
        }
        
        .markdown-renderer .overflow-x-auto::-webkit-scrollbar-track {
          background: #f1f1f1;
          border-radius: 3px;
        }
        
        .markdown-renderer .overflow-x-auto::-webkit-scrollbar-thumb {
          background: #888;
          border-radius: 3px;
        }
        
        .markdown-renderer .overflow-x-auto::-webkit-scrollbar-thumb:hover {
          background: #555;
        }
        
        /* 暗黑模式滚动条 */
        .dark .markdown-renderer .overflow-x-auto::-webkit-scrollbar-track {
          background: #1a202c;
        }
        
        .dark .markdown-renderer .overflow-x-auto::-webkit-scrollbar-thumb {
          background: #4a5568;
        }
        
        .dark .markdown-renderer .overflow-x-auto::-webkit-scrollbar-thumb:hover {
          background: #718096;
        }
        
        /* API表格特殊样式 */
        .markdown-renderer table.api-table th:first-child {
          width: 20%;
        }
        .markdown-renderer table.api-table th:nth-child(2) {
          width: 30%;
        }
        .markdown-renderer td:first-child {
          font-weight: 500;
        }
        .markdown-renderer td:nth-child(2) {
          font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
          font-size: 0.85em;
          color: #0969da;
          white-space: pre-wrap;
          word-break: break-word;
        }
        .markdown-renderer td:nth-child(3) {
          color: #57606a;
          font-style: italic;
        }
        
        /* 暗黑模式样式 */
        .dark .markdown-renderer table { 
          border-color: #334155; 
          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
        }
        .dark .markdown-renderer th {
          background-color: #1e293b;
          color: #f1f5f9;
          border-bottom-color: #334155;
        }
        .dark .markdown-renderer td { border-bottom-color: #334155; }
        .dark .markdown-renderer tbody tr:nth-child(even) { background-color: #1a2234; }
        .dark .markdown-renderer tbody tr:hover { background-color: #283042; }
        .dark .markdown-renderer td:nth-child(2) { color: #58a6ff; }
        .dark .markdown-renderer td:nth-child(3) { color: #94a3b8; }
        .dark .markdown-renderer td code {
          background-color: rgba(99, 110, 123, 0.4);
        }
        
        /* 数学公式样式增强 */
        .katex-display {
          overflow-x: auto;
          overflow-y: hidden;
          padding: 1rem 0;
          margin: 1.5rem 0 !important;
        }
        .katex {
          font-size: 1.1em;
          text-align: center;
          line-height: 1.5em;
        }
        .katex-html {
          overflow-x: auto;
          overflow-y: hidden;
        }
        /* 块级公式样式 */
        .math.math-display {
          display: block;
          overflow-x: auto;
          margin: 1.5rem 0;
          padding: 1rem;
          background-color: rgba(248, 250, 252, 0.5);
          border-radius: 0.5rem;
          border: 1px solid #e2e8f0;
        }
        /* 行内公式样式 */
        .math.math-inline {
          padding: 0.1em 0.2em;
        }
        /* 暗黑模式数学公式样式 */
        .dark .math.math-display {
          background-color: rgba(30, 41, 59, 0.5);
          border-color: #334155;
        }
        .dark .katex {
          color: #f1f5f9;
        }
        
        /* 全局溢出控制 */
        .markdown-renderer {
          width: 100%;
          overflow-x: hidden;
        }
        .markdown-renderer img,
        .markdown-renderer pre,
        .markdown-renderer code,
        .markdown-renderer * {
          max-width: 100%;
        }
        
        /* 确保代码块不会导致水平溢出 */
        .markdown-renderer pre {
          overflow-x: auto;
          border-radius: 0.375rem;
          margin: 1rem 0 !important;
        }
        
        /* 处理过长的表格和内容 */
        .markdown-renderer table {
          margin-left: auto;
          margin-right: auto;
        }
        
        /* 表格单元格样式优化 */
        .markdown-renderer td, 
        .markdown-renderer th {
          white-space: normal;
          word-break: break-word;
        }
        
        /* 根据内容类型调整单元格的空间处理 */
        .markdown-renderer td pre,
        .markdown-renderer td code {
          white-space: pre;
        }
      `}</style>
      <ReactMarkdown
        remarkPlugins={remarkPlugins}
        rehypePlugins={rehypePlugins}
        components={{
          // @ts-expect-error 使用inline参数
          code({ inline, className, children, ...props }) {
            const match = /language-(\w+)/.exec(className || "");
            const language = match && match[1] ? match[1] : "";

            return !inline && match ? (
              <CodeBlock language={language} className={className} {...props}>
                {String(children).replace(/\n$/, "")}
              </CodeBlock>
            ) : (
              <code
                className={`rounded px-1 py-0.5 bg-gray-100 dark:bg-gray-800 text-gray-800 dark:text-gray-200 ${
                  className || ""
                }`}
                {...props}
              >
                {children}
              </code>
            );
          },
          pre({ children, ...props }) {
            return (
              <pre
                className=" dark:bg-gray-800 bg-gray-100 rounded-md p-4 overflow-x-auto max-w-full"
                {...props}
              >
                {children}
              </pre>
            );
          },
          a({ href, children, ...props }) {
            return (
              <a
                href={href}
                className="text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300 hover:underline"
                target="_blank"
                rel="noopener noreferrer"
                {...props}
              >
                {children}
              </a>
            );
          },
          img({ src, alt, ...props }) {
            return (
              <img
                src={src}
                alt={alt}
                className="rounded-md max-w-full my-4"
                loading="lazy"
                {...props}
              />
            );
          },
          table({ children, ...props }) {
            // 检测是否为API文档风格表格（通过检查表头是否包含"属性"、"类型"、"默认值"等关键词）
            const childrenString = String(children);
            const isApiTable =
              childrenString.toLowerCase().includes("属性") ||
              childrenString.toLowerCase().includes("参数") ||
              childrenString.toLowerCase().includes("property") ||
              childrenString.toLowerCase().includes("attribute");

            return (
              <div className="overflow-x-auto w-full my-6 relative">
                <table
                  className={`min-w-full divide-y divide-gray-200 dark:divide-gray-700 ${
                    isApiTable ? "api-table" : ""
                  }`}
                  {...props}
                >
                  {children}
                </table>
              </div>
            );
          },
          thead({ children, ...props }) {
            return (
              <thead
                className="text-xs uppercase tracking-wider sticky top-0 z-10"
                {...props}
              >
                {children}
              </thead>
            );
          },
          tbody({ children, ...props }) {
            return (
              <tbody
                className="divide-y divide-gray-200 dark:divide-gray-700 text-sm"
                {...props}
              >
                {children}
              </tbody>
            );
          },
          tr({ children, ...props }) {
            return (
              <tr className="transition-colors" {...props}>
                {children}
              </tr>
            );
          },
          th({ children, ...props }) {
            return (
              <th
                scope="col"
                className="px-4 py-3 font-semibold text-left"
                {...props}
              >
                {children}
              </th>
            );
          },
          td({ children, ...props }) {
            // 检查是否包含代码元素或类型定义格式
            const childrenStr = String(children);
            const containsCode =
              childrenStr.includes("`") ||
              /\([^)]*\)\s*=>/.test(childrenStr) ||
              /[A-Z][a-zA-Z]+(<[^>]+>)?(\[\])?/.test(childrenStr) ||
              /(?:boolean|string|number|object|symbol|undefined|null|void|never|any)(\[\])?/.test(
                childrenStr
              ) ||
              /["|']\w+["|']/.test(childrenStr);

            // 处理类似 ReactNode, string[], boolean 等类型标记
            const formattedChildren =
              typeof children === "string"
                ? children
                    // 处理函数类型，如 () => void
                    .replace(
                      /(\([^)]*\))\s*(=>)\s*([a-zA-Z<>[\]|\s]+)/g,
                      '<span style="color: var(--syntax-entity-color)">$1 $2 $3</span>'
                    )
                    // 处理常见类型名称
                    .replace(
                      /\b(string|number|boolean|object|any|void|null|undefined|never|unknown|Promise|React|ReactNode|FC|Component|Props)(\[\])?\b/g,
                      '<span style="color: var(--syntax-keyword-color)">$1$2</span>'
                    )
                    // 处理泛型类型 Array<T>, Promise<T> 等
                    .replace(
                      /\b([A-Z][a-zA-Z]*)(<[^>]+>)(\[\])?/g,
                      '<span style="color: var(--syntax-entity-color)">$1$2$3</span>'
                    )
                    // 处理字符串字面量类型
                    .replace(
                      /(['"][\w-]+['"])\s*(\|)?\s*/g,
                      '<span style="color: var(--syntax-string-color)">$1</span>$2 '
                    )
                : children;

            return (
              <td className="px-4 py-3" {...props}>
                {containsCode && typeof formattedChildren === "string" ? (
                  <div
                    dangerouslySetInnerHTML={{ __html: formattedChildren }}
                    style={
                      {
                        "--syntax-keyword-color": "#d73a49",
                        "--syntax-entity-color": "#6f42c1",
                        "--syntax-string-color": "#032f62",
                      } as React.CSSProperties
                    }
                    className="dark:text-gray-300 font-mono text-xs sm:text-sm"
                  />
                ) : (
                  children
                )}
              </td>
            );
          },
          blockquote({ children }) {
            return (
              <blockquote className="border-l-4 border-gray-300 dark:border-gray-700 pl-4 py-2 my-4 italic bg-gray-50 dark:bg-gray-800/50 text-gray-700 dark:text-gray-300">
                {children}
              </blockquote>
            );
          },
          hr() {
            return (
              <hr className="border-t border-gray-300 dark:border-gray-700 my-6" />
            );
          },
          h1({ children, ...props }) {
            return (
              <h1
                className="text-3xl font-bold mt-8 mb-4 text-gray-900 dark:text-gray-100"
                {...props}
              >
                {children}
              </h1>
            );
          },
          h2({ children, ...props }) {
            return (
              <h2
                className="text-2xl font-bold mt-6 mb-3 text-gray-900 dark:text-gray-100"
                {...props}
              >
                {children}
              </h2>
            );
          },
          h3({ children, ...props }) {
            return (
              <h3
                className="text-xl font-bold mt-5 mb-2 text-gray-900 dark:text-gray-100"
                {...props}
              >
                {children}
              </h3>
            );
          },
          h4({ children, ...props }) {
            return (
              <h4
                className="text-lg font-bold mt-4 mb-2 text-gray-900 dark:text-gray-100"
                {...props}
              >
                {children}
              </h4>
            );
          },
          h5({ children, ...props }) {
            return (
              <h5
                className="text-base font-bold mt-3 mb-1 text-gray-900 dark:text-gray-100"
                {...props}
              >
                {children}
              </h5>
            );
          },
          h6({ children, ...props }) {
            return (
              <h6
                className="text-sm font-bold mt-2 mb-1 text-gray-900 dark:text-gray-100"
                {...props}
              >
                {children}
              </h6>
            );
          },
          ul({ children, className, ...props }) {
            // 检查是否是任务列表
            const isTaskList =
              className?.includes("contains-task-list") || false;
            return (
              <ul
                className={`${
                  isTaskList ? "list-none pl-0" : "list-disc pl-6"
                } my-4 ${className || ""}`}
                {...props}
              >
                {children}
              </ul>
            );
          },
          ol({ children, ...props }) {
            return (
              <ol className="list-decimal pl-6 my-4" {...props}>
                {children}
              </ol>
            );
          },
          // @ts-expect-error 自定义任务列表项
          li({ children, className, checked, ...props }) {
            // 处理任务列表项
            if (className === "task-list-item") {
              return (
                <TaskListItem checked={checked === true}>
                  {children}
                </TaskListItem>
              );
            }
            return (
              <li className="my-1" {...props}>
                {children}
              </li>
            );
          },
        }}
      >
        {processedContent}
      </ReactMarkdown>
    </div>
  );
};

export default MarkdownRenderer;
